#ifndef UTILS_H
#define UTILS_H

#include <unistd.h>
#include <fstream>
#include <cstdlib>
#include <map>

#include "logger.h"

#define VERSION "0.0.1"

#define HELP " \
Usage: tinystl [options] [catagory] [modules]\n\n \
Example: \n \
    tinystl -lcontainer vector \n \
    \n \
    -l, --list  List out the content of a module \n \
        catagories: \n \
            [ adapter | algorithm | container | datastructure | functional | iterator ] \n \
    -v, --version   Show version \n \
    -h, --help  You're looking at it \n \
" \

namespace tinystl
{

    const std::map<int, std::string> LIB = {
        {1, "stl/adapter/"}
    };

    class Utils    {
        public:
            static void checkOption(int argc, char *argv[]) noexcept{
                int option;
                const char *optstring = "hl::v";
                while ((option = getopt(argc, argv, optstring)) != -1)
                {
                    switch (option)
                    {
                        case 'h':
                            Logger::instance()->log(HELP);
                            break;
                        case 'v':
                            Logger::instance()->log(VERSION);
                            break;
                        case 'l':
                            if (optarg)
                            {
                                judgeCatagories(optarg);
                            }
                            else
                            {
                                Logger::instance()->log("Please exactly specify a doc name (eg. LinkList.h)");
                                system("tree stl/");
                            }
                            break;
                        default:
                            break;
                    }
                }
            }

            static void readFile(const char *file)
            {
                std::ifstream fin;
                fin.open(file);
                if (!fin)
                {
                    Logger::instance()->log("Load file failed");
                    return;
                }
                char ch;
                while (EOF != (ch = fin.get()))
                    Logger::instance()->log(ch);
                fin.close();
            }
        private:
            inline static void judgeCatagories(char* ...) noexcept
            {
                std::string opta = optarg;
                std::string cmd = "less stl/";

                if (opta == "priority_queue_adapter")
                {
                    cmd.append("adapter/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "queue_adapter")
                {
                    cmd.append("adapter/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "reverse_iterator_adapter")
                {
                    cmd.append("adapter/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "stack_adapter")
                {
                    cmd.append("adapter/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "sorting_methods")
                {
                    cmd.append("algorithm/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "allocator")
                {
                    cmd.append("allocator/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "constructor")
                {
                    cmd.append("allocator/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "basic_string")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "deque")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "list")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "map")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "set")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "unordered_map")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "unordered_set")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "vector")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "cir_queue")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "link_list")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "seq_list")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "seq_stack")
                {
                    cmd.append("datastructure/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "functional")
                {
                    cmd.append("functional/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "hash_functional")
                {
                    cmd.append("functional/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else if (opta == "iterator")
                {
                    cmd.append("iterator/");
                    cmd.append(opta);
                    cmd.append(".h");
                    system(cmd.c_str());
                }
                else
                {
                    Logger::instance()->log("Please exactly specify a doc name (eg. LinkList.h)");
                    system("tree stl/");
                }
            }
    };
};
#endif
